/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Application;
import Application.Elements.Element;
import Application.Elements.Oszc;
import java.util.*;

/**
 * Fo halozat osztaly, gyakorlatilag ez a modell, egy kontener a halozati elemeknek.
 * @author Stikmann
 */
public class Network implements CheckResetSimulate{


    /**
     * Az osszes vezerelt kaput tartalmazo kollekcio.
     */
    protected List<CheckResetSimulate> collection;
    /**
     * Ebben a kollekcioban taroljuk kulon az osszcilloszkopokat, mert ezeket 
     * kulon kell kiertekelni.
     */
    protected List<Oszc> oszcCollection;
    
    /**
     * A hálózat osztály konstruktora
     */
    public Network(){
        SkeletonHelper.methodstart("Constructed "+this);
        collection=new ArrayList();
        SkeletonHelper.methodend();
    }


    @Override
    public String toString() {
        // Szep outputot szeretnenk a skeletonhelperben.
        return this.getClass().getSimpleName()+"@"+Integer.toHexString(this.hashCode());
    }

    /**
     * Elvegzi a tarolt elemek szimulaciojat.
     * @exception UnstableException ha a hálózat nem stabil
     * @return Ha változott bármi is, true, ha nem, false
     * @todo a fentebbi állítást el ne felejtsd megcsinálni.
     */
    public boolean simulate() throws UnstableException{
        SkeletonHelper.methodstart(this.toString()+"::simulate()");

        // Ez a ciklus addig fusson amig van valtozas a halozat allapotaban,
        // vagy tul sokszor le nem fut.
        do{
            for (CheckResetSimulate elem:collection)
            //Visszateresi erteke, hogy volt e valtozas az elem kimeneteben.
                elem.simulate();
        } while (SkeletonHelper.kerdez("Valtozott a halozat allapota (menjen tovabb a szimulacios ciklus)?"));

        // Itt kell leelenorizni, hogy valoban a valtozas hianya miatt alltunk le,
        // vagy tul sokszor futott le a ciklus.
        if (SkeletonHelper.kerdez("A tul sok iteracio miatt allt le a szimulacio?"))
        {
            SkeletonHelper.methodend("throw UnstableException");
            throw new UnstableException();
        }
        
        // Kiertekeljuk az oszcilloszkopokat, ha mar stabil a halozat, marpedig
        // itt stabil. A kiertekeles a tobbi elemhez hasonloan tortenik.
        for (Oszc o:oszcCollection) {
            o.simulate();
        }
        
        // Ha a fenti csodaciklus pontosan egyszer futott le, false,
        // egyébként true
        SkeletonHelper.methodend("return: ???");
        return false;
    }

    /**
     * Alaphelyzetbe allitja az osszes tarolt kaput.
     */
    public void reset(){
        SkeletonHelper.methodstart(this.toString()+"::reset()");

        for (CheckResetSimulate elem:collection)
                elem.reset();
        SkeletonHelper.methodend();
    }

    /**
     * Leellenorzi, hogy van-e hiba a halozatban
     * @return Ha nincs hiba, null, egyebkent a hibauzenet.
     */
    public String check(){
        SkeletonHelper.methodstart(this.toString()+"::check()");
        String hiba=null;
        for (CheckResetSimulate elem:collection)
        {
             hiba=elem.check();
             if (hiba!=null)
             {
                 hiba="Hiba egy "+elem.getClass().getSimpleName()+" tipusu elemnel: "+hiba;
                break;
             }
        }

        SkeletonHelper.methodend("return: "+hiba);
        return hiba;
    }

    /**
     * Hozzaad egy kaput vagy alhálózatot a halozathoz
     * @param mit Az objektum amit hozzaadunk
     */
    public void addGate(CheckResetSimulate mit)
    {
        SkeletonHelper.methodstart(this.toString()+"::addGate("+mit+")");
        collection.add(mit);
        SkeletonHelper.methodend();
    }

    /**
     * osszekot ket kaput a halozatban
     * @param src A forras elem, aminek a kimenetet kotjuk
     * @param dst A cel elem, aminek a bemenetere kotunk
     */
    public void connectGate(Element src, Element dst)
    {
        SkeletonHelper.methodstart(this.toString()+"::connectGate("+src+", "+dst+")");
        dst.connectTo(src);
        SkeletonHelper.methodend();
    }
    
    /**
     * Oszcilloszkop hozzadasa a hallozathoz
     * @param mit az elemre mutato referencia
     */
    public void addOszc(Oszc mit) {
        oszcCollection.add(mit);
    }
    /**
     * Oszcilloszkop hozzakotese valamelyik elemhez
     * @param src a hozzakotendo oszcilloszkop
     * @param dst az elem amihez hozzakotjuk
     */
    public void connectOszc(Oszc src, Element dst) {
        src.connectTo(dst);
    }

}